﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading;

namespace ECMessageQueue
{
    public class MessageQueue
    {
        protected Thread senderThread;
        protected bool isRunning = true;

        protected ECLogger.Logger log;

        [Serializable]
        public class MQMESSAGE
        {
            public int remote;
            public string content;
            public int length;
            public string token;
        }

        protected List<MQMESSAGE> msgRecv;
        protected List<MQMESSAGE> msgSend;

        public MessageQueue(ECLogger.Logger logger = null)
        {
            msgRecv = new List<MQMESSAGE>();
            msgSend = new List<MQMESSAGE>();
            log = logger;
        }

        public void runSender()
        {
            senderThread = new Thread(new ThreadStart(() =>
            {
                while (isRunning)
                {
                    try
                    {
                        if (msgSend.Count > 0)
                        {
                            var msg = msgSend[0];
                            if (msg != null)
                            {
                                sendBySocket(msg);
                                msgSend.RemoveAt(0);
                            }
                            else
                            {
                                Exception ex = new Exception("Message Sender ERROR.");
                                throw ex;
                            }
                        }
                        else Thread.Sleep(10);
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }
            }));
            senderThread.Start();
        }

        public void stopSender()
        {
            if (senderThread != null) senderThread.Abort();
        }

        protected virtual void sendBySocket(MQMESSAGE mqm) { }

        public void sendMessage(MQMESSAGE mqm)
        {
            msgSend.Add(mqm);
        }

        protected void putRecvQueue(MQMESSAGE mqm)
        {
            msgRecv.Add(mqm);
        }

        public MQMESSAGE getMessage()
        {
            while (isRunning)
            {
                if (msgRecv.Count > 0)
                {
                    MQMESSAGE mqm;
                    mqm = msgRecv[0];
                    msgRecv.RemoveAt(0);
                    return mqm;
                }
                else Thread.Sleep(20);
            }
            return null;
        }

        protected byte[] msgToBytes(MQMESSAGE mqm)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                IFormatter fmt = new BinaryFormatter();
                fmt.Serialize(ms, mqm);
                return ms.GetBuffer();
            }
        }

        protected MQMESSAGE bytesToMsg(byte[] buffer)
        {
            try
            {
                using (MemoryStream ms = new MemoryStream(buffer))
                {
                    IFormatter fmt = new BinaryFormatter();
                    return (MQMESSAGE)fmt.Deserialize(ms);
                }
            }
            catch (Exception)
            {
                return null;
            }
        }

        protected string genToken(int length = 16)
        {
            string token = string.Empty;
            string s = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
            var rnd = new Random();
            for (int i = 0; i < length; i++)
            {
                token += s[rnd.Next(0, 61)];
            }
            return token;
        }
    }
}
